#ifndef ARC_CACHE_LRU_PART_H
#define ARC_CACHE_LRU_PART_H

#include "ARCCacheNode.h"
#include <mutex>
#include <unordered_map>

using namespace std;
namespace Cache {
template <typename Key, typename Value> class ArcLRUPart {
public:
    using NodeType = ArcNode<Key, Value>;
    using NodePtr = shared_ptr<NodeType>;
    using NodeMap = unordered_map<Key, NodePtr>;

    explicit ArcLRUPart(size_t capacity, size_t transformThreshold)
        : capacity_(capacity), ghostCapacity_(capacity), transformThreshold_(transformThreshold) {
        initializeLists();
        // cout << "Successful ArcLRUPart construct" << endl;
    }

    bool put(Key k, Value v) {
        if (!capacity_)
            return false;
        lock_guard<mutex> lock(mutex_);
        auto it = mainCache_.find(k);
        if (it != mainCache_.end())
            return updateExistingNode(it->second, v);
        return addNewNode(k, v);
    }

    bool get(Key k, Value &v, bool &shouldTransform) {
        lock_guard<mutex> lock(mutex_);
        auto it = mainCache_.find(k);
        if (it == mainCache_.end())
            return false;

        shouldTransform = updateNodeAccess(it->second);
        v = it->second->getValue();
        return true;
    }

    bool checkGhost(Key k) {
        auto it = ghostCache_.find(k);
        if (it == ghostCache_.end())
            return false;
        removeFromGhost(it->second);
        ghostCache_.erase(it);
        return true;
    }

    void increaseCapacity() {
        capacity_++;
    }

    bool decreaseCapacity() {
        if (capacity_ <= 0)
            return false;
        if (mainCache_.size() == capacity_)
            evictLeastRecent();
        capacity_--;
        return true;
    }

private:
    void initializeLists() {
        mainHead_ = make_shared<NodeType>();
        mainTail_ = make_shared<NodeType>();
        ghostHead_ = make_shared<NodeType>();
        ghostTail_ = make_shared<NodeType>();

        mainHead_->next_ = mainTail_;
        mainTail_->prev_ = mainHead_;

        ghostHead_->next_ = ghostTail_;
        ghostTail_->prev_ = ghostHead_;
    }

    bool addNewNode(const Key &k, const Value &v) {
        if (mainCache_.size() == capacity_)
            evictLeastRecent(); // 驱逐最近最少访问
        NodePtr newNode = make_shared<NodeType>(k, v);
        mainCache_[k] = newNode;
        addToFront(newNode, mainHead_);
        return true;
    }

    void addToFront(NodePtr n, NodePtr head) {
        n->prev_ = head;
        n->next_ = head->next_;

        head->next_->prev_ = n;
        head->next_ = n;
    }

    void addToGhost(NodePtr n) {
        // 重置访问计数
        n->accCount_ = 1;

        // 添加到头部
        addToFront(n, ghostHead_);
        ghostCache_[n->getKey()] = n;
    }

    void moveToFront(NodePtr n) {
        n->prev_->next_ = n->next_;
        n->next_->prev_ = n->prev_;
        addToFront(n, mainHead_);
    }

    bool updateExistingNode(NodePtr n, Value v) {
        n->setValue(v);
        moveToFront(n);
        return true;
    }

    bool updateNodeAccess(NodePtr n) {
        moveToFront(n);
        n->increaseAccCount();
        return n->getAccCount() >= transformThreshold_;
    }

    void removeFromGhost(NodePtr n) {
        n->prev_->next_ = n->next_;
        n->next_->prev_ = n->prev_;
    }

    void removeFromMain(NodePtr n) {
        n->prev_->next_ = n->next_;
        n->next_->prev_ = n->prev_;
    }

    void removeOldestGhost() {
        NodePtr oldestGhost = ghostTail_->prev_;
        if (oldestGhost == ghostHead_)
            return;
        removeFromGhost(oldestGhost);
        ghostCache_.erase(oldestGhost->getKey());
    }

    void evictLeastRecent() {
        NodePtr leastRecent = mainTail_->prev_;
        if (leastRecent == mainHead_)
            return;
        // 移出主链表
        removeFromMain(leastRecent);

        // 加入幽灵链表
        if (ghostCache_.size() >= ghostCapacity_)
            removeOldestGhost();
        addToGhost(leastRecent);

        mainCache_.erase(leastRecent->getKey());
    }

private:
    size_t capacity_;
    size_t ghostCapacity_;
    size_t transformThreshold_; // 转换阈值
    mutex mutex_;

    NodeMap mainCache_;
    NodeMap ghostCache_;

    // 主链表
    NodePtr mainHead_;
    NodePtr mainTail_;

    // 淘汰链表
    NodePtr ghostHead_;
    NodePtr ghostTail_;
};
} // namespace Cache

#endif